package com.btcode.db.connection;

import com.alibaba.druid.filter.stat.StatFilter;
import com.alibaba.druid.pool.DruidDataSource;
import com.btcode.db.config.DataBaseConfig;
import java.util.Collections;

/**
 * 提供默认的连接池对象，这里会设置好常规的连接池设置，上层应用可以拿到这个对象后再进行自定义，减少编码
 */
public class DruidDataSourceHelp {

    public static DruidDataSource getDefault(DataBaseConfig config){
        DruidDataSource dataSource = new DruidDataSource();

        dataSource.setUsername(config.getUserName());
        dataSource.setPassword(config.getPassword());
        dataSource.setUrl(config.getConnectionString());
        dataSource.setDriverClassName(config.getDirverClass());

        dataSource.setInitialSize(1);//初始化时建立物理连接的个数。初始化发生在显示调用init方法，或者第一次getConnection时
        dataSource.setMinIdle(1);//setKeepAlive
        dataSource.setMaxActive(90);//最大连接

        dataSource.setPoolPreparedStatements(false);

        //用来检测连接是否有效的sql，要求是一个查询语句，常用select 'x'。如果validationQuery为null，testOnBorrow、testOnReturn、testWhileIdle都不会起作用。
        dataSource.setValidationQuery("select 'x'");
        dataSource.setValidationQueryTimeout(30);//单位：秒，检测连接是否有效的超时时间。底层调用jdbc Statement对象的void setQueryTimeout(int seconds)方法
        dataSource.setTestOnBorrow(true);//申请连接时执行validationQuery检测连接是否有效，做了这个配置会降低性能。默认true
        dataSource.setTestOnReturn(false);//归还连接时执行validationQuery检测连接是否有效，做了这个配置会降低性能。默认false
        dataSource.setTestWhileIdle(true);//建议配置为true，不影响性能并且保证安全性。申请连接时检测，如果空闲时间大于timeBetweenEvictionRunsMillis，执行validationQuery检测连接是否有效

        dataSource.setKeepAlive(true);//连接池中的minIdle数量以内的连接，空闲时间超过minEvictableIdleTimeMillis，则会执行keepAlive操作。
                /*有两个含义：1) Destroy线程会检测连接的间隔时间，如果连接空闲时间大于等于minEvictableIdleTimeMillis则关闭物理连接。
                            2) testWhileIdle的判断依据，详细看testWhileIdle属性的说明*/
        dataSource.setTimeBetweenEvictionRunsMillis(10000);
        dataSource.setMinEvictableIdleTimeMillis(600000);//连接保持空闲而不被驱逐的最小时间
        dataSource.setMaxEvictableIdleTimeMillis(900000);

        dataSource.setRemoveAbandoned(true);//连接泄露监测,超过下面设置时间得不活跃连接会清除
        dataSource.setRemoveAbandonedTimeout(1800);
        dataSource.setLogAbandoned(true);

        dataSource.setTimeBetweenLogStatsMillis(120000);//监控时间间隔
        StatFilter filter = new StatFilter();
        filter.setSlowSqlMillis(1000);
        filter.setLogSlowSql(true);//检测慢sql
        filter.setMergeSql(false);//检测merge语句
        filter.setConnectionStackTraceEnable(true);
        dataSource.setProxyFilters(Collections.singletonList(filter));//日志过滤器

        return dataSource;
    }

}
